package com.iot.core.utils;

import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import org.apache.commons.lang3.StringUtils;

import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.*;

public class BeanUtils {

    public static void copyMapToObject(Map<String, Object> map, Object o) {
        if (map == null || o == null) {
            return;
        }
        Set<String> set = map.keySet();
        Class c = o.getClass();
        Field[] fields = c.getDeclaredFields();
        for (Field f : fields) {
            f.setAccessible(true);
            if (set.contains(f.getName())) {
                if ((f.getGenericType().toString()).equals("class java.util.Date") && null != map.get(f.getName())) {
                    //处理时间类型
                    try {
                        f.set(o, DateUtils.parse(map.get(f.getName()).toString()));
                    } catch (IllegalAccessException e) {
                        e.printStackTrace();
                    }
                } else {
                    try {
                        f.set(o, map.get(f.getName()));
                    } catch (IllegalAccessException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }

    public static void copyJSONToObject(JSONObject json, Object o) {
        if (json == null || o == null) {
            return;
        }
        Set<String> set = json.keySet();
        Class c = o.getClass();
        Field[] fields = c.getDeclaredFields();
        for (Field f : fields) {
            f.setAccessible(true);
            if (set.contains(f.getName())) {
                if ((f.getGenericType().toString()).equals("class java.util.Date") && null != json.get(f.getName())) {
                    //处理时间类型
                    try {
                        f.set(o, DateUtils.parse(json.get(f.getName()).toString()));
                    } catch (IllegalAccessException e) {
                        e.printStackTrace();
                    }
                } else {
                    try {
                        f.set(o, json.get(f.getName()));
                    } catch (IllegalAccessException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }

    public static Map<String, Object> transBean2Map(Object obj, Map<String, Object> map) {
        if (obj == null) {
            return null;
        }
        try {
            BeanInfo beanInfo = Introspector.getBeanInfo(obj.getClass());
            PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
            for (PropertyDescriptor property : propertyDescriptors) {
                String key = property.getName();
                // 过滤class属性
                if (!key.equals("class") && !key.equals("pageSO")) {
                    // 得到property对应的getter方法
                    Method getter = property.getReadMethod();
                    Object value = getter.invoke(obj);
                    if (null != value && !"".equals(value)) {
                        map.put(key, value);
                    }
                }

            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return map;
    }

    public static <T> T copyJSONToObject(JSONObject json, Class<T> clazz) {
        T o = null;
        try {
            o = clazz.newInstance();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        if (json == null) {
            return o;
        }
        Set<String> set = json.keySet();
        Class c = o.getClass();
        Field[] fields = c.getDeclaredFields();
        for (Field f : fields) {
            f.setAccessible(true);
            if (set.contains(f.getName())) {
                if (null != json.get(f.getName())) {
                    if ((f.getGenericType().toString()).equals("class java.util.Date")) {
                        //处理时间类型
                        try {
                            if (!StringUtils.isBlank(json.get(f.getName()).toString())) {
                                f.set(o, DateUtils.parse(json.get(f.getName()).toString()));
                            }
                        } catch (IllegalAccessException e) {
                            e.printStackTrace();
                        }
                    } else if ((f.getGenericType().toString()).equals("class java.lang.Double")) {
                        try {
                            if (!StringUtils.isBlank(json.get(f.getName()).toString())) {
                                f.set(o, Double.valueOf(json.get(f.getName()).toString()));
                            }
                        } catch (IllegalAccessException e) {
                            e.printStackTrace();
                        }
                    } else {
                        try {
                            f.set(o, json.get(f.getName()));
                        } catch (IllegalAccessException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
        }
        return o;
    }

    /**
     * 获取相同对象集合中指定字段a集合中有b集合中无的该字段集合
     *
     * @param a
     * @param b
     * @param field
     * @param <T>
     * @return
     */
    public static <T> List<String> getAHasBNoFields(List<T> a, List<T> b, String field) {
        List<String> res = Lists.newArrayList();
        List<String> aFields = Lists.newArrayList();
        List<String> bFields = Lists.newArrayList();
        for (T t : a) {
            try {
                aFields.add(getGetMethod(t, field).toString());
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        for (T t : b) {
            try {
                bFields.add(getGetMethod(t, field).toString());
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        for (String aField : aFields) {
            if (!bFields.contains(aField)) {
                res.add(aField);
            }
        }
        return res;
    }

    /**
     * 获取相同对象集合中指定字段为标准，a集合中有b集合中无的该实体对象集合
     *
     * @param a
     * @param b
     * @param field
     * @param <T>
     * @return
     */
    public static <T> List<T> getAHasBNoList(List<T> a, List<T> b, String field) {
        List<T> res = Lists.newArrayList();
        List<String> bFields = Lists.newArrayList();
        for (T t : b) {
            try {
                bFields.add(getGetMethod(t, field).toString());
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        for (T t : a) {
            try {
                if (!bFields.contains(getGetMethod(t, field).toString())) {
                    res.add(t);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return res;
    }

    /**
     * 比较ab两个集合中keyField字段相同的compareField字段不同b集合中的元素
     *
     * @param a
     * @param b
     * @param keyField
     * @param compareField
     * @param <T>
     * @return
     */
    public static <T> List<T> getADifferBList(List<T> a, List<T> b, String keyField, String compareField) {
        List<T> res = Lists.newArrayList();
        for (T t1 : a) {
            try {
                for (T t2 : b) {
                    if (getGetMethod(t1, keyField).equals(getGetMethod(t2, keyField))) {
                        if (!getGetMethod(t1, compareField).equals(getGetMethod(t2, compareField))) {
                            res.add(t2);
                        }
                        break;
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return res;
    }

    /**
     * 根据属性，获取get方法
     *
     * @param ob   对象
     * @param name 属性名
     * @return
     * @throws Exception
     */
    public static Object getGetMethod(Object ob, String name) throws Exception {
        Method[] m = ob.getClass().getMethods();
        for (int i = 0; i < m.length; i++) {
            if (("get" + name).toLowerCase().equals(m[i].getName().toLowerCase())) {
                return m[i].invoke(ob);
            }
        }
        return null;
    }

    /**
     * 复制source的值到target
     *
     * @param source
     * @param target
     * @return
     */
    public static <T> void copyObjectToAnother(T source, T target) {
        if (null == source) {
            return;
        }
        if (null == target) {
            try {
                target = (T) target.getClass().newInstance();
            } catch (InstantiationException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }
        try {
            Class targetClz = target.getClass();
            Class sourceClz = source.getClass();
            Field[] fields = sourceClz.getDeclaredFields();
            for (int i = 0; i < fields.length; i++) {
                fields[i].setAccessible(true);
                Field f = targetClz.getDeclaredField(fields[i].getName());
                f.setAccessible(true);
                //只拷贝有值得属性
                Object obj = fields[i].get(source);
                if (null != obj) {
                    if (obj instanceof String) {
                        if (!StringUtils.isBlank(obj.toString())) {
                            f.set(target, obj);
                        }
                    } else {
                        f.set(target, obj);
                    }
                }
            }
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        }
    }
}
